#!/usr/bin/python

import threading, Queue, time

class BaseFloodManager (threading.Thread):
	def __init__ (self, say, notice):
		self.say_callback = say
		self.notice_callback = notice
		self.queue = Queue.Queue(0)
		threading.Thread.__init__(self)
		self.setDaemon(True)
		self.continueRunning = True
	
	def send (self, msg):
		# msg : ("channel", "Message", boolean noticing)
		self.queue.put(msg)
	
	def sendItem (self, item):
		if item[2] == True:
			# noticing
			self.notice_callback(item[0], item[1])
		else:
			self.say_callback(item[0], item[1])
		
	def handle (self, item):
		self.sendItem(item)
		
	def run(self):
		while True:
			item = self.queue.get()
			if not(self.continueRunning):
				break
			self.handle(item)
	
	def stop (self):
		self.continueRunning = False
		self.queue.put((None, None, None))

class WaitingFloodManager (BaseFloodManager):
	def __init__ (self, say, notice):
		BaseFloodManager.__init__ (self, say, notice)
		self.last_messages_times = []
	
	def handle (self, item):
		self.last_messages_times.append(time.time())
		for msgTime in self.last_messages_times:
			if msgTime < time.time() - 3:
				self.last_messages_times.remove(msgTime)
		time.sleep(len(self.last_messages_times) - 1)
		self.sendItem(item)

class DroppingFloodManager (BaseFloodManager):
	def __init__ (self, say, notice):
		BaseFloodManager.__init__ (self, say, notice)
		self.last_messages = {} # {message time => message length}
		self.floodtime = 0
		
	def handle (self, item):
		if self.floodtime + 5 > time.time():
			# If we're in the "flooding" state, stop now.
			return
		msg = item[1]
		min_time = time.time() - 10
		for send_time in self.last_messages.keys():
			if send_time < min_time:
				del self.last_messages[send_time]
		total_size = len(msg)
		for msg_len in self.last_messages.values():
			total_size += msg_len
		if total_size > 2000 or len(self.last_messages.values()) > 10:
			self.floodtime = time.time()
			self.sendItem((item[0], "Risk of excess flood...", item[2]))
			try:
				while True:
					self.queue.get_nowait()
			except:
				pass
		else:
			self.last_messages[time.time()] = len(msg)
			self.sendItem(item)


class NullFloodManager (BaseFloodManager):
	def handle (self, item):
		self.sendItem(item)

FloodManager = WaitingFloodManager